home *** CD-ROM | disk | FTP | other *** search
- HOW TO CRACK, by +ORC, A TUTORIAL
-
- ---------------------------------------------------------------------------
-
- Lesson 3.1: hands on, paper protections (1)
-
- ---------------------------------------------------------------------------
-
- [UMS.EXE] [LIGHTSPD.EXE] [GENERAL.EXE]
-
- --------------------------------------
-
- SOME PROBLEMS WITH INTEL's INT
- The INT instruction is the source of a great deal of the
- flexibility in the PC architecture, because the ability to get
- and set interrupt vectors means that system services (included
- DOS itself) are infinitely extensible, replaceable and
- MONITORABLE. Yet the Int instruction is also remarkably
- inflexible in two key ways:
- - an interrupt handler DOES NOT KNOW which interrupt number
- invoked it.
- - the int instruction itself expects an IMMEDIATE operand:
- you cannot write MOV AX,x21, and then INT AX; you must
- write INT x21.
- That would be very good indeed for us cracker... unfortunately
- many high level language compilers compile interrupts into PUSHF
- and FAR CALL instruction sequences, rather than do an actual INT.
- Another method is to PUSH the address of the handler on the stack
- and do RETF to it.
- Some protection schemes attempt to disguise interrupt calls,
- 1) camouflaging the code, 2) putting in substitute interrupt
- instructions which look harmless and modifying them "on the fly"
- or 3) replicating whole interrupt routines inside the code. This
- is particularly frequent in the various "disk access" protection
- schemes that utilize INT_13 (the "disk" interrupt) and will
- therefore be thoroughly explained in -> lesson 5.
-
- A LITTLE BASIC ASSEMBLER
- In order to understand the protection schemes and to defeat them,
- you must acquire a passing knowledge of assembler, the "machine
- language" code. You can find a lot of good, well explained code
- for free: viruses are one of the best sources for good "tight and
- tricky" assembler code. You can find the source code of almost
- all viruses on the web: oddly all the would be hackers seem to
- have an aberrant passion for this kind of stuff instead of
- studying cracking techniques. But there are millions of lines of
- good explained "commercial" assembler code on the net, just fish
- it out and study it: the more you know, the better you crack.
- I'll restrict myself to some observations, sprinkled throughout
- this tutorial. Let's start with some must_know:
- ------------------------ STRINGS ----------------------------
- The string instructions are quite powerful (and play a great role
- in password protection scheme). ALL of them have the property
- that:
- 1) The source of data is described by the combination DS:SI
- 2) The destination of data is described by the combination
- ES:DI
- 3) As part of the operation, the SI and/or DI register(s)
- is(are) incremented or decremented so the operation can be
- repeated.
- ------------------------- JUMPS -----------------------------
- JZ ero means what it says
- JNZ ero means what it says
- JG reater means "if the SIGNED difference is positive"
- JA bove means "if the UNSIGNED difference is positive"
- JL ess means "if the SIGNED difference is negative"
- JB elow means "if the UNSIGNED difference is negative"
- JC arry assembles the same as JB, it's a matter of
- aesthetic choice
-
- CRACKING PASSWORD PROTECTED PROGRAMS
- Refer to lesson one in order to understand why we are using
- games instead of commercial applications as learn material: they
- offer the same protection used by the more "serious" applications
- (or BBS & servers) although inside files that are small enough
- to be cracked without loosing too much time.
- A whole series of programs employ copy protection schemes
- based upon the possess of the original manual or instructions.
- That's obviously not a very big protection -per se- coz everybody
- nowadays has access to a photocopier, but it's bothering enough
- to motivate our cracks and -besides- you'll find the same schemes
- lurking in many other password protected programs.
- Usually, at the beginning of the program, a "nag screen"
- requires a word that the user can find somewhere inside the
- original manual, something like: "please type in the first word
- of line 3 of point 3.3.2". Often, in order to avoid mistakes, the
- program indicates the first letter of the password... the user
- must therefore only fill the remaining letters.
-
- Some examples, some cracks:
- ---------------------------------------------------
- UMS (Universal Military Simulator) version 1
- by Dr Ezra SIDRAN
- (c) 1987 Intergalactic Development
- European Union: Rainbird Software
- United States: Firebird Software
- ---------------------------------------------------
- This very old EGA program is one of the first I cracked in
- my youth, and it's very interesting coz it employs a very basilar
- protection scheme (a "PRIMITIVE"! More than 80% of the protection
- schemes used to day (January 1996) are directly derived from one
- of the 12 primitives.
- The nag screen snaps at the beginning and keeps indefinitely
- asking your answer, only the use of CTRL+C will bring you out of
- it, back to DOS. That's a clear sign of older protection schemes:
- newer schemes let you in for only 3 attempts or even only one,
- and pop out to the OS if you fail. In UMS, besides, there is no
- "first letter" aid, a later improvement.
- The cracking procedure for password protected programs is,
- first of all, to find out where are stored the letters that you
- type in. So examine your memory map, find out where the program
- dwells in memory, do a snap save of these memory areas and a
- series of snap compares as you type your password in.
- Strangely enough, in the case of UMS, as you type your
- password there seems to be no difference at all in the memory
- locations where this program dwells... yet the data must be
- somewhere... Usually such a situation is a clear sign that an
- hooked interrupt is used to hide the data.
- Checking the hooked vectors you find out the following:
- vecs 00, 02, 22 are hooked where needs be
- vecs 34-3D are hooked at xxxx:0
- vec 3E is hooked at xxxx:00CA
- Ha! Let's have a closer look at this bizarre 3E hook. Let's
- search for some words used in the nag_screen and then let's dump
- the area where we find them (in UMS that will be at 3E_hook
- address + 7656) and loo! You'll see the content of the nag screen
- and, immediately afterwards, ALL the passwords "in extenso", i.e.
- not encoded, not scrambled, nothing at all... THERE THEY ARE
- (that's a very old protection scheme indeed). You could now, for
- instance, easily patch all the different passwords to (for
- instance) "PASS", and this would work... it's a very primitive
- protection, as we said, nevertheless the use of a hooked vector
- as hiding place for the protection code is not yet obsolete...
- we'll find it elsewhere, in many "more modern" programs.
- Now let's go deeper and examine the "compare" mechanism, we
- want to crack, here, not just to patch.
- Password protected programs (and access protection routines
- for server and BBS, for that matter) have quite a lot of weak
- points. The most obvious one (you 'll find out the other when
- you'll high crack) is that they MUST compare the password of the
- user with the original one(s). So you do not need to steal a
- password, you just need to "ear" the echo of the original one in
- the memory locations used for the compare, or, and that's more
- correct, to crack the compare mechanism itself so as to make it
- let you in even with a totally false password.
- The compare mechanism of UMS can be found setting a
- breakpoint on the memory range that covers the three locations
- where the password is stored (and you 'll find these with your
- search capabilities and with a pair of snap compares):
- ES:0F8E (here you 'll see a copy of the password that the
- program is asking)
- ES:0F5C (here you 'll see a copy of the password that the user
- types in)
- INT_3E hook_address + 7656 (here are all the possible passwords
- in extenso).
-
- Here is how the protection scheme looks out:
-
- MOV CX,FFFF Charge MAX in CX
- REPNZ SCASB Scan ES:DI (the user password)
- NOT CX Now CX holds the number of the
- character that the user typed in
- MOV DI,SI Real password offset to DI
- LDS SI,[BP+0A] User password offset in SI
- REPZ CMPSB Compares DS:SI with ES:DI (user
- password and real password) then snap
- out at CX=0 or at char_different,
- whichever comes first.
- Nice, we found the compare schema... how do we crack it now?
- There are many elegant solutions, but let's remain on a basic
- level... you look at the code that follows the CMPSB searching
- the "snapping schema"... here it is immediately afterwards
- (that's the case in most of the primitives). Remember: we sprung
- out of the CMPSB check at the first different char, OR at the end
- of the count of the user chars. Here it is what follows:
- MOV AL,[SI-01] loads in AL the before_different char
- of the user password (should be zero)
- SUB AL,ES:[DI-01] subs with the before_different char of
- the real password (should be zero)
- CBW zero flag set, "TRUE", if OK_match
- Well let's now look for the next JZ near (it's a "74" code)
- CS:IP 740D JZ location no_good
- Wait, let's continue a little... is there another check (often
- you have a double check on DI)... yes there is!
- CS:IP 7590 JNZ location no_good
- Cracking such a schema is very easy: you just need to substitute
- 75 to 74 and 74 to 75: transform your JZ in a JNZ and the JNZ in
- a JZ... now you will always pass, no matter what you write,
- unless you exactly guess the password!
-
- Now let's quickly crack it:
- ------------------------------------------------
- CRACKING UMS.EXE (by +ORC, January 1996)
-
- ren ums.exe ums.ded
- symdeb ums.ded
- - s (cs+0000):0 Lffff 74 0D 1E B8 C2 3F
- (nothing)
- - s (cs+1000):0 Lffff 74 0D 1E B8 C2 3F
- (nothing)
- - s (cs+2000):0 lffff 74 0D 1E B8 C2 3F
- xxxx:yyyy (this is the answer of the debugger)
- - e xxxx:yyyy 75
- - e xxxx:yyyy+17 74
- - w
- - q
- ren ums.ded ums.exe
- -------------------------------------------------
-
- In the debug/symdeb crack above we use as search string the
- bytes comprising and following immediately the first JZ.
- I know, I know... we saw them in [Soft-ice] and we could have
- modified them there, but I'm teaching also pupils who may not
- have [Soft-ice].
- Note that the program is x431A0 bytes long, and therefore
- has a BX=4 sectors adding to the CX=31A0 in the initial
- registers... that's the reason I wanted to examine all the
- sectors (even if I knew that the snap was in sector (cs+2000):
- that's good practice! If you do not find your string in the first
- sector you must search for it in the next sectors, till you find
- it, coz in many programs there may be MORE THAN ONE repetitions
- of the same schema (more about this double check later).
- That's it, pupils, that's the way to crack old [UMS.EXE].
-
- Let's go over, now, to more elaborate and more modern password
- protection schemes.
-
- --------------------------------------------------------
- LIGHTSPEED, from Microprose (we crack here version 461.01)
- --------------------------------------------------------
- This program, released in 1990, operates a more "modern"
- variation of the previous scheme. You 'll find this variation in
- many access routines of remote servers (and this makes it very
- interesting indeed).
- Let's begin as usual, with our hooked vectors examination
- and our snap compares.
- Hooked vectors: 00, 08, 1B, 22, 23: nothing particular.
- The snap_comparisons of the main memory area -as you type the
- password in- gives more than six pages of changing locations...
- that's clearly much too much to examine.
- What now?
- Sit down, have a Martini Wodka (I'm afraid that only
- Moskovskaja 'll do) and meditate. Get the memory map of the
- program's layout. Start anew: snap_save (before typing anything
- in). Type as password "ABCDE". Get the print of the snap
- compares. Sit down, sip Martini Wodka, relax. You know that the
- code for A is x41, for B x42, for C x43 and so on... and in the
- snap_compares, that you made between letters, you 'll have only
- some locations with these values changing. Focus on these.
- You 'll soon enough find out that for LIGHTSPEED absolute
- location (in my computer) 404307, i.e.: relative locations (in
- my computer) 30BE:F857 or 4043:0007 evoke the characters you
- type, i.e. something like
- -----------------------------------------------------
- F855 F856 F857 F858 F859...
- 41 3E first_ready_letter your_1st_letter your_2nd_one...
- -----------------------------------------------------
- Inspecting the same prints, you 'll find out that absolute
- location 30C64 (imc) or relative location 30BE:F83E evokes the
- LAST character you typed in. The relative code line is:
- CS:0097 MOV AX,[BP-08] where SS:F83E = 00+letter_code
- Now breakpoint at these locations and investigate what's
- going on (for instance, the instruction that follows is
- CS:009A MOV [BX], AX
- and this means that the code of the letter you just typed in will
- be now copied in BX=F85A. What else can you do? Time to use a
- little intuition: look for an instruction "CMP AX,000D", which
- is the typical "IF the user hits ENTER then" instruction, coz
- "x1D" its the ENTER keystroke. This must be somewhere around
- here. Ha! You 'll soon enough find the line
- CS:0073 3D0D00 CMP AX,000D
- And now the way is open to the crack. But YOU DO NOT NEED ALL
- THIS! Since the password protection schemes are -as I told you-
- all more or less the same, I would suggest that you use first of
- all following trick: in the largest part of the program (use
- memory map to see where the program dwells) search the "F3A6"
- sequence, that's instruction REPZ CMPSB.
- In the case of Lightspd you 'll get as answer FOUR addresses
- with this instruction: (pgsg=program main segment)
- pgsg:C6F9
- pgsg:E5CA
- pgsg:E63E
- pgsg:EAB0
- There you are! Only four... have a short look at each of them:
- you 'll see that the second one (pgsg:E5CA) is the "good" one.
- The compare mechanism in this program of 1990 it's more or less
- the same as in 1987'UMS (and do believe me: the same mechanism
- is still in use to day (1996)!
- B9FFFF MOV CX,FFFF charge Max in CX
- F2AE REPNZ SCASB this scans ES:DI (the original
- password)
- F7D1 NOT CX so many chars in the original pw
- 2BF9 SUB DI,CX change DI for compare
- F3A6 REPZ CMPSB compares DS:SI with ES:DI (real
- pw with user pw) then snaps out
- at CX=0 or at char_differs
- See how easy? They all use the same old tricks the lazy
- bastards! Here the section is preceded by a small routine to
- lowercase the user password, coz the original muster is always
- lowercased.
- Now you would like, may be, to breakpoint at one of these
- locations, in order to stop the program "in the snap area" and
- inspect the snap mechanism... that WILL NOT DO with a "fixed"
- breakpoint, coz these locations are called by the snap with a
- different segment:offset numeration as the one you found (that's
- old dos magic). So you MUST first set a memory_read/write
- breakpoint on these locations, and then get at them at the snap.
- Now you can find out the segment:offset used by the snap and only
- now you'll be able to set a fixed breakpoint (for instance on the
- NOT CX instruction).
- Now run the program and breakpoint in: have a dump of the
- ES:DI and see the original password. How nice! We have now the
- original password in extenso in our memory dump window. That's
- the "echo". By the way, there is a whole school of cracking
- devoted to find and use these echoes... we work on different
- paths, nevertheless password fishing can be interesting: where
- are the password stored? From which locations do they come from?
- A common practice of the protectionists is to hide them in
- different files, far away, or in hooked vectors, or in SMC parts.
- This is a program of 1990, that differs in respect to UMS: the
- passwords are not "hidden" inside a hooked vector, coz that's a
- pretty stupid protection: any hexdump utility would still permit
- you to see them. Here the passwords are encoded (albeit in a very
- primitive manner): looking for them (with memory range
- breakpoints) you'll quickly find a section of the program code
- that looks like this:
- sg:0118 8C 91 9D 95 9B 8D 00 B8 EC 94 9B 8D 8F 8B 9B
- sg:0128 94 9B 8D 00 AE EC 9C 9B 8A 9B 86 00 A9 EC 91
- This is a typical encoded matrix, with clear 00 fences between
- the encoded passwords.
- Ha! If all codes where so easy to crack! This is no better than
- children's crypt! It's a NEG matrix! And there is direct
- correspondence: 91=6F="o"; 92=6E="n"; 93=6D="m" and so on... Ha!
- Let's now leave the "hidden" passwords and proceed with our
- cracking... let's follow the snap procedure after the REPZ CMPSB
- instruction looking for the "jump to OK" instruction...
- F3A6 REPZ CMPSB ; compares DS:SI with ES:DI
- 7405 JZ preserved_AX=0000 <--- Here the first JZ
- 1BC0 SBB AX,AX
- ADFFFF SBB AX,FFFF
- :preserved_AX=0000
- 8BF3 MOV SI,BX
- 8BFA MOV DI,DX
- 5D POP BP
- CB RETF
- ....
- 83C404 ADD SP,+04
- 0BC0 OR AX,AX
- 7509 JNZ 0276 <------ And here it is!
- Now, remembering the UMS crack, you would probably want to
- change the JZ instruction in a JNZ instruction (you tried it on
- the fly INSIDE [Soft-Ice] and it did work!), the "74" with a
- "75" also. And then you would like to change the JNZ instruction
- in a JZ instruction... Please feel free to try it... it will NOT
- work! (You will not even find the second JNZ in the program
- code). You should always be aware of the SMC (self modifying
- code) protections: parts of the code my be decrypted "on the
- fly", as needs arise, by the program. The code you modify while
- the program is running may be different from the code of the
- "dead" program.
- Here we have a small "improvement" of the primitive: the
- same instruction is used as "muster" for manipulation of other
- parts of the program... if you do change it in a JNZ you get an
- overlay message and the program pops out with instability! You
- cannot easily modify the JNZ instruction either, coz the part
- after the RETF will be compiled "on the fly" by lightspeed, and
- you would therefore have to search the decryption mechanism and
- modify the original encrypted byte somewhere... and may be they
- do encrypt it twice... and then you must hack all night long...
- very annoying.
- So do the following: back to the snap, a sip of martini-
- Wodka and meditate: loo! The only thing that happens after the
- JZ, is the setting of the AX register to flag *FALSE* (AX=1...
- that's what the two SBB instructions do) if the snap went out
- with a non-zero flag... i.e. if you did not know the password.
- So let's nop the 5 bytes of the two SBB instructions, or, more
- elegantly, let's have a INC AX, DEC AX, NOP, INC AX, DEC AX
- sequence instead of the two SBB! There is a good reason to use
- a sequence of working instructions instead of a series of NOPs:
- recent protection schemes "smell" patched nops inside the program
- and trash everything if they find more than -say- three
- consecutive NOPs! You should always try to choose THE LESS
- INTRUSIVE and MORE "CAMOUFLAGED" solution when you crack!
- Eliminating the two SBBs we get our crack! No need to bother
- with the second JNZ either... the program will work as if you got
- the password if you have it AND if you do not (that's better as
- the previous type of crack -seen for UMS- when you crack computer
- accesses: hereby the legitimate user will not have any suspects
- 'coz the system will not shut him out... everybody will access:
- the good guys and the bad ones... that's nice isn't it?).
-
- Now let's quickly crack LIGHTSPD:
- ------------------------------------------------
- CRACKING LIGHTSPEED.EXE (by +ORC, January 1996)
-
- ren lightspd.exe lightspd.ded
- symdeb lightspd.ded
- - s (cs+0000):0 Lffff 2B F9 F3 A6 74
- xxxx:yyyy (this is the answer of the debugger)
- - s (cs+1000):0 Lffff 2B F9 F3 A6 74
- (nothing, but do it nonetheless, just to be sure)
- - s (cs+2000):0 lffff 2B F9 F3 A6 74
- (nothing, just to be sure, now it's enough)
- - e xxxx:yyyy+6 40 [SPACE] 48 [SP] 90 [SP] 40 [SP] 48
- - w
- - q
- ren lightspd.ded lightspd.exe
- -------------------------------------------------
-
- All this CMPSB is very common. Some programs, nevertheless,
- utilize a password protection scheme that is slightly different,
- and does not rely on a F3A6 REPZ CMPSB instruction. Let's
- analyze, for instance, the protection scheme used in the first
- version of Perfect general I from QQP-White wolf, July 1992.
- When you break in, at the nag screen, you are in the middle of
- the BIOS procedures, coz the program expects your input (your
- password, that's is). You 'll quickly find out (MAP MEMORY
- USAGE!) that [General.exe] dwells in two main areas; Setting
- breakpoints on memory write you 'll find out that the memory area
- "queried" by the protection mechanism is
- xxxx:1180 to xxxx:11C0
- where xxxx represents the second of the memory segments where the
- program dwells. Now do the following (a very common cracking
- procedure):
- * Breakpoint on memory range WRITE for the small memory area
- touched by the program in querying you for the password.
- * Breakpoint TRACE on the whole memory range of the MAIN
- CODE.
- * Run anew everything
- It's already done! Now it's your intuition that should work a
- little: Here the last 9 traces (traces [!], not instructions
- following on a line) before the calling of the procedure sniffing
- your memory area:
-
- -9 xxxx:0185 7425 JZ somewhere, not taken
- -8 xxxx:0187 2D1103 SUB AX,0311
- -7 xxxx:018A 7430 JZ somewhere, not taken
- -6 xxxx:018C 2DFD04 SUB AX,04FD
- -5 xxxx:018F 7443 JZ next_trace, taken
- -4 xxxx:01D4 E85500 CALL funny_procedure
- -3 xxxx:022C 803E8F8C11 CMP BYTE PTR[8C8F],11
- -2 xxxx:0231 750E JNZ somewhere, not taken
- -1 xxxx:0233 9A0A0AC33E CALL procedure_that_sniffs
- our_memory_area
-
- Well, the call to funny_procedure followed by a byte compare
- "feels" fishy from very far away, so let's immediately look at
- this part of the code of [General.exe]
- :funny_procedure
- 803E8F8C11 CMP BYTE PTR[8C8F],11
- 750E JNZ compare_byte
- 9A0A0AC333 CALL procedure_that_sniffs
- 0AC0 OR AL,AL
- 7405 J2 compare_byte
- C6068F8C2A MOV BYTE PTR [8C8F],2A
- :compare_byte
- 803E8F8C2A CMP BYTE PTR [8C8F],2A
- 7504 JNZ after_ret
- B001 MOV AL,01
- C3 RET
- You should be enough crack-able ;=), by this lesson, to notice
- immediately the inconsistency of the two successive instructions
- MOV 2A and CMP 2A, coz there would be no sense in comparing the
- "2A" in order to JNZ to after_ret if you just had the 2A set with
- the precedent MOV instruction... but the first JNZ jumps to the
- compare WITHOUT putting the "2A" inside. And "2A" is nothing else
- as the "*" symbol, commonly used by programmer as "OK"! This
- protection works in the following way (this is the above code
- explained):
- - compare holy_location with 11
- - jump non zero to compare holy_loc with "*"
- - else call sniffing protection part
- - or al,al (al must be zero, else)
- - jump zero to compare holy_loc with "*"
- - if al was zero mov "*" inside holy_loc
- - compare holy_loc with "*"
- - if there is a difference then JNZ beggar_off_ugly_copier
- - else ret_ahead_nice_buyer
-
- Now let's quickly crack it:
- ------------------------------------------------
- CRACKING GENERAL.EXE (by +ORC, January 1996)
-
- ren general.exe general.ded
- symdeb general.ded
- - s (cs+0000):0 Lffff 8C 11 75 0E
- xxxx:yyyy (this is the answer of the debugger)
- - e xxxx:yyyy+2 EB [SPACE] 09
- - w
- - q
- ren general.ded general.exe
- -------------------------------------------------
- And in this way you changed the JNZ to the cmp "*" instruction
- in a JMP to the mov "*" instruction. So no more nag screens, no
- more protections... serene, placid, untroubled [general.exe].
-
- Well, that's it for this lesson, reader. Not all lessons of my
- tutorial are on the Web.
- You 'll obtain the missing lessons IF AND ONLY IF you mail
- me back (via anon.penet.fi) with some tricks of the trade I may
- not know that YOU discovered. Mostly I'll actually know them
- already, but if they are really new you'll be given full credit,
- and even if they are not, should I judge that you "rediscovered"
- them with your work, or that you actually did good work on them,
- I'll send you the remaining lessons nevertheless. Your
- suggestions and critics on the whole crap I wrote are also
- welcomed.
-
- E-mail +ORC
-
- +ORC an526164@anon.penet.fi
-